package moa.tasks;

import moa.core.ObjectRepository;
import moa.learners.Learner;
import moa.options.ClassOption;
import moa.options.IntOption;
import moa.streams.InstanceStream;

public class SequenceTask extends MainTask {

	public ClassOption learnerOption = new ClassOption("learner", 'l',
			"Classifier to train.", Learner.class, "GSPSequenceFrequenceMiner");

	public ClassOption streamOption = new ClassOption("stream", 's',
			"Stream to learn from.", InstanceStream.class,
			"generators.RandomTreeGenerator");

	public IntOption maxInstancesOption = new IntOption("numberOfInstances", 'm',
			"Number of instances to show.",
			10, 0, Integer.MAX_VALUE);
	
	public SequenceTask (Learner learner, InstanceStream stream,
			int maxInstances, int numPasses) {
		this.learnerOption.setCurrentObject(learner);
		this.streamOption.setCurrentObject(stream);
		this.maxInstancesOption.setValue(maxInstances);
		//this.numPassesOption.setValue(numPasses);
	}
	
	@Override
	protected Object doMainTask(TaskMonitor monitor, ObjectRepository repository) {
		Learner learner = (Learner) getPreparedClassOption(this.learnerOption);
		InstanceStream stream = (InstanceStream) getPreparedClassOption(this.streamOption);
		learner.setModelContext(stream.getHeader());
		int numPasses = 1; //this.numPassesOption.getValue();
		int maxInstances = this.maxInstancesOption.getValue();
		
		for (int pass = 0; pass < numPasses; pass++) {
			long instancesProcessed = 0;
			monitor.setCurrentActivity("Training learner"
					+ (numPasses > 1 ? (" (pass " + (pass + 1) + "/"
							+ numPasses + ")") : "") + "...", -1.0);
			if (pass > 0) {
				stream.restart();
			}
			while (stream.hasMoreInstances() && ((maxInstances < 0) || (instancesProcessed < maxInstances))) {
				learner.trainOnInstance(stream.nextInstance());
				instancesProcessed++;
				// Update of the monitor
				if (instancesProcessed % INSTANCES_BETWEEN_MONITOR_UPDATES == 0) {
					if (monitor.taskShouldAbort()) {
						return null;
					}
					long estimatedRemainingInstances = stream
							.estimatedRemainingInstances();
					if (maxInstances > 0) {
						long maxRemaining = maxInstances - instancesProcessed;
						if ((estimatedRemainingInstances < 0)
								|| (maxRemaining < estimatedRemainingInstances)) {
							estimatedRemainingInstances = maxRemaining;
						}
					}
					monitor
							.setCurrentActivityFractionComplete(estimatedRemainingInstances < 0 ? -1.0
									: (double) instancesProcessed
											/ (double) (instancesProcessed + estimatedRemainingInstances));
					if (monitor.resultPreviewRequested()) {
						monitor.setLatestResultPreview(learner.copy());
					}
				}
				// End of the monitor 
			}
		}
		learner.setModelContext(stream.getHeader());
		return learner;
	}

	@Override
	public Class<?> getTaskResultType() {
		// TODO Auto-generated method stub
		return null;
	}

}
